#include "sc_wifi_mgr.h"
#include <../wifi_mgmr.h>
#include <wifi_mgmr_ext.h>
#include <FreeRTOS.h>
#include <semphr.h>
#include <string.h>
#include "WifiConfig_hal_sys_api.h"

static wifi_mgmr_ap_item_t *ap_ary_p;
static int counter;
static uint8_t channel_used[15]; /* 14 channel + [0](unused) */

static void cb_scan_item_parse(wifi_mgmr_ap_item_t *env, uint32_t *param1, wifi_mgmr_ap_item_t *item)
{
    /* item->channel start at 1 */
    channel_used[item->channel] = 1;
    memcpy(&ap_ary_p[counter], item, sizeof(wifi_mgmr_ap_item_t));
    counter++;
}

static void cb_scan_complete(void *data, void *param)
{
    SemaphoreHandle_t sc_scan_sem = (SemaphoreHandle_t)data;

    counter = 0;
    wifi_mgmr_scan_ap_all(ap_ary_p, NULL, cb_scan_item_parse);
    printf("sc scan complete:%ld \r\n", counter);

    if (sc_scan_sem) {
        xSemaphoreGive(sc_scan_sem);
    }
}

int sc_scan_init(void)
{
    ap_ary_p = (wifi_mgmr_ap_item_t *)malloc(sizeof(wifi_mgmr_ap_item_t) * WIFI_MGMR_SCAN_ITEMS_MAX);
    if (NULL == ap_ary_p)
    {
        return -1;
    }

    return 0;
}

void sc_scan_deinit(void)
{
    if (NULL != ap_ary_p)
    {
        free(ap_ary_p);
    }
}

int sc_scan_start(void)
{
    SemaphoreHandle_t sc_scan_sem = NULL;

    if (NULL == ap_ary_p)
    {
        return -1;
    }

    sc_scan_sem = xSemaphoreCreateBinary();
    if (NULL == sc_scan_sem) {
        return -1;
    }

    axk_hal_wifi_mode_set(1, 0);
    
    memset(channel_used, 0, sizeof(channel_used));
    memset(ap_ary_p, 0, sizeof(wifi_mgmr_ap_item_t) * WIFI_MGMR_SCAN_ITEMS_MAX);

    wifi_mgmr_scan_adv(sc_scan_sem, cb_scan_complete, NULL, 0, NULL, 0, 220000);
    xSemaphoreTake(sc_scan_sem, portMAX_DELAY);
    vSemaphoreDelete(sc_scan_sem);

    return 0;
}

/**
 * @brief get next available channel
 * 
 * @param chan_cur current channel, start at 1
 * @return channel
 */
int sc_get_next_channel(int chan_cur)
{
    int chan_first;
    int chan;

    chan_first = 1;
    for (chan = 1; chan < sizeof(channel_used); chan++) {
        if (channel_used[chan] != 0) {
            if (chan_first != 1) {
                chan_first = chan;
            }
            if (chan <= chan_cur) {
                continue;
            }
            break;
        }
    }
    if (chan == sizeof(channel_used)) {
        chan = chan_first;
    }

    return chan;
}

wifi_mgmr_ap_item_t *sc_scan_get_ap_by_bssid(uint8_t *bssid)
{
    if (NULL == ap_ary_p)
    {
        return NULL;
    }

    for (int i = 0; i < WIFI_MGMR_SCAN_ITEMS_MAX; i++) {
        if (memcmp(ap_ary_p[i].bssid, bssid, 6) == 0) {
            return &ap_ary_p[i];
        }
    }

    return NULL;
}
